# -*- coding: utf-8 -*-
"""Sample model module."""

import logging
log = logging.getLogger(__name__)
import transaction
import time

from attr import AttrObj, AttrContainer

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# RoleDefAttr
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
class RoleDefAttr(AttrObj):
    pass

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# RoleDef
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
class RoleDef(AttrContainer):
    """
    currentSC and targetSC are inline to reduce DB access
    all the rest of the attrs are in tbRoleDefAttr table
    """
    def addDependOn(self,roledef,local=False):
        if local:
            self.dependOnLocal.append(roledef)
        else:
            self.dependOn.append(roledef)
            
    def __new__(cls, *args, **kwds):
#        print "RoleDef.__new__", args, kwds
        cls.AttrClass=RoleDefAttr
        return AttrContainer.__new__(cls, *args, **kwds)
        
    def __init__(self,myname="",mydoc="",mymapping="",profiletype=""):
        super(RoleDef, self).__init__()
        self.AttrClass=RoleDefAttr
        
        self.setAttr("name",myname)
        self.setAttr("doc",mydoc)
        self.setAttr("profile",mymapping)
        self.setAttr("profiletype",profiletype)

    def __repr__(self):
        return "RoleDef(name=%s, doc=%s, profile=%s, profiletype=%s)" % (self.getAttr("name"),self.getAttr("doc"),self.getAttr("profile"),self.getAttr("profiletype"))

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# RoleAttr
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
class RoleAttr(AttrObj):
    pass

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Role
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
class Role(AttrContainer):
    """
    currentSC and targetSC are inline to reduce DB access
    all the rest of the attrs are in tbRoleAttr table
    """
    class SC:
        nSC=8
        (SC_INITIALIZED,
         SC_STARTINGVM,
         SC_APPLYING,
         SC_RUNNING,
         SC_REMOVING,
         SC_STOPPINGVM,         
         SC_FIXING,
         SC_EXCEPTION)=range(nSC)
        SC_STARTED=SC_RUNNING
        SC_STOPPED=SC_INITIALIZED
        canTarget=[SC_INITIALIZED,SC_RUNNING, SC_EXCEPTION]

    def __new__(cls, *args, **kwds):
#        print "Role.__new__", args, kwds
        cls.AttrClass=RoleAttr

        Role.SCname={}
        for i in Role.SC.__dict__.keys():
            if i.find('SC_')>=0:
                Role.SCname[Role.SC.__dict__[i]]=i

        return AttrContainer.__new__(cls, *args, **kwds)
        

    def __init__(self,name="DummyRole",roledef=None,enabled=True,vm=None):
        super(Role, self).__init__()

        self.AttrClass=RoleAttr

        self.roleDef=roledef
        self.vm=vm

        self.setAttr("name",name)
        self.setAttr("enabled",str(enabled))
        
        self.currentSC=self.SC.SC_INITIALIZED
        self.targetSC=self.SC.SC_STOPPED

    def __repr__(self):
        return "Role(name=%s, enabled=%s)" % (self.getAttr("name"),self.getAttr("enabled"))

    def setEnabled(self,enabled):
        if enabled:
            strenable="True"
        else:
            strenable="False"
        self.setAttr("enabled",strenable)

        for ir in self.dependOnLocal:
            ir.setEnabled(enabled)

    def getProfileProvided(self):
        return self.getAttr("ProfileProvided")=="True"
    
    def getProfileApplied(self):
        return self.getAttr("ProfileApplied")=="True"

    def setProfileProvided(self,p):
        if p:
            self.setAttr("ProfileProvided","True")
        else:
            self.setAttr("ProfileProvided","False")

    def setProfileApplied(self,p):
        if p:
            self.setAttr("ProfileApplied","True")
        else:
            self.setAttr("ProfileApplied","False")
    
    def getReverseProfileProvided(self):
        return self.getAttr("ReverseProfileProvided")=="True"
    
    def getReverseProfileApplied(self):
        return self.getAttr("ReverseProfileApplied")=="True"

    def setReverseProfileProvided(self,p):
        if p:
            self.setAttr("ReverseProfileProvided","True")
        else:
            self.setAttr("ReverseProfileProvided","False")
            
    def setReverseProfileApplied(self,p):
        if p:
            self.setAttr("ReverseProfileApplied","True")
        else:
            self.setAttr("ReverseProfileApplied","False")
    


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# VMAttr
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
class VMAttr(AttrObj):
    pass

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# VM
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
class VM(AttrContainer):
    """
    currentSC and targetSC are inline to reduce DB access
    all the rest of the attrs are in tbVMAttr table
    """
    class SC:
        nSC=6
        (SC_INITIALIZED,
         SC_STARTING,
         SC_RUNNING,
         SC_STOPPING,
         SC_FIXING,
         SC_EXCEPTION)=range(nSC)
        SC_STARTED=SC_RUNNING
        SC_STOPPED=SC_INITIALIZED
        canTarget=[SC_INITIALIZED,SC_RUNNING, SC_EXCEPTION]

    def __new__(cls, *args, **kwds):
#        print "VM.__new__", args, kwds
        cls.AttrClass=VMAttr
        
        VM.SCname={}
        for i in VM.SC.__dict__.keys():
            if i.find('SC_')>=0:
                VM.SCname[VM.SC.__dict__[i]]=i

        return AttrContainer.__new__(cls, *args, **kwds)

    def __init__(self,name="DummyVM", rp=None):

        super(VM, self).__init__()
        self.AttrClass=VMAttr
        self.rp=rp
        self.setAttr("name",name)
        self.currentSC=self.SC.SC_INITIALIZED
        self.targetSC=self.SC.SC_STOPPED

    def __repr__(self):
        if self.rp is None:
            return "VM(name=%s, rp=%s)" % (self.getAttr("name"),"None")
        return "VM(name=%s, rp=%s)" % (self.getAttr("name"),self.rp.getAttr("name"))        

    def getStarted(self):
        return self.getAttr("Started")=="True"

    def setStarted(self,p):
        if p:
            self.setAttr("Started","True")
        else:
            self.setAttr("Started","False")


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ClusterAttr
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
class ClusterAttr(AttrObj):
    pass

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Cluster
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
class Cluster(AttrContainer):
    """
    currentSC and targetSC are inline to reduce DB access
    all the rest of the attrs are in tbClusterAttr table
    """
    class SC:
        nSC=6
        (SC_INITIALIZED,
         SC_STARTING,
         SC_RUNNING,
         SC_STOPPING,
         SC_FIXING,
         SC_EXCEPTION)=range(nSC)
        SC_STARTED=SC_RUNNING
        SC_STOPPED=SC_INITIALIZED
        canTarget=[SC_INITIALIZED,SC_RUNNING, SC_EXCEPTION]

    def __new__(cls, *args, **kwds):
#        print "VM.__new__", args, kwds
        cls.AttrClass=ClusterAttr
        
        Cluster.SCname={}
        for i in Cluster.SC.__dict__.keys():
            if i.find('SC_')>=0:
                Cluster.SCname[Cluster.SC.__dict__[i]]=i

        return AttrContainer.__new__(cls, *args, **kwds)

    def __init__(self,name="DummyCluster"):

        super(Cluster, self).__init__()

        self.AttrClass=ClusterAttr
        
        self.setAttr("name",name)
        self.currentSC=self.SC.SC_INITIALIZED
        self.targetSC=self.SC.SC_STOPPED

    def addRole(self, roledef, vm, name=None, enabled=True):
        if roledef is None or vm is None:
            raise RuntimeError("Must provide roledef and vm")
        if name is None:
            name="role_%s"%roledef.getAttr("name")

        aRole=Role(name=name,roledef=roledef,enabled=enabled,vm=vm)

        #Fix dependencies
        #Two type of dependencies
        # 1. global dependency (dependOn):
        #    If a RoleDef has other RoleDef globally depend on it (local=False), there should be at most one Role that realizes this RoleDef.
#        for irole in self.role:
#            if irole.roleDef in aRole.roleDef.dependOn: #aRole dependOn iRole
#                aRole.dependOn.append(irole)
        #This is handled by buildRoleDep() in crvtools.py
        
        self.role.append(aRole)

        # 2. local dependency (dependOnLocal):
        #    If a RoleDef A locally depend on another RoleDef B, when A realizes to a Role, B realizes to another Role in the same VM.
        for ird in roledef.dependOnLocal:
            iRole=Role(name="autorole_%s_%s"%(name,ird.getAttr("name")), roledef=ird, enabled=enabled,vm=vm)
            aRole.dependOnLocal.append(iRole)
            self.role.append(iRole)

        return aRole
    
